package gdou.gym.socket;


import com.fasterxml.jackson.databind.ObjectMapper;
import gdou.gym.entity.SiteApplication;
import gdou.gym.exception.StateCode;
import gdou.gym.exception.SysException;
import gdou.gym.service.space.SpaceService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Comparator;
import java.util.concurrent.ConcurrentHashMap;


/*目前仅支持俩用户在线发送
 * 离线消息可以通过 一个时间戳记录发送者发送的时间，并用一个map存放，
 * 即该用户的消息队列
 * 然后下次用户连接时可以遍历该队列,依次发送
 * */

@Controller
@Slf4j
@ServerEndpoint(value = "/admin/{act}")
public class AdminSocketServer {
    private static final ThreadLocal<ObjectMapper> local = ThreadLocal.withInitial(ObjectMapper::new);
    //存储客户端的连接对象,每个客户端连接都会产生一个连接对象
    private static final ConcurrentHashMap<String, AdminSocketServer> map = new ConcurrentHashMap<>();
    //每个连接都会有自己的会话
    private Session session;
    private String account;

    private static final Object V = new Object();
    private static final ConcurrentHashMap<String, Object> SESSION = new ConcurrentHashMap<>();
    private static final ConcurrentHashMap<AdminSocketServer, String> a = new ConcurrentHashMap<>();





    private static SpaceService spaceService;

    @Autowired
    public void setSpaceService(SpaceService x) {
        spaceService = x;
    }

    @OnOpen
    public void open(@PathParam("act") String account,
                     Session session) {
        log.info("管理员:{}登陆了", account);
        //WsSession
        this.session = session;
        this.account = account;
        map.put(account, this);
    }


    public static void request(SiteApplication request) throws IOException {
        if (map.isEmpty()) return;
        SocketResponseEntry responseEntry = new SocketResponseEntry(request, SocketResponseEntry.SocketResponse.SEND_REQUEST_TO_ADMIN);
        map.forEachValue(5, v -> v.send(responseEntry));
    }

    private void send(SocketResponseEntry request) {
        try {
            send(local.get().writeValueAsString(request));
        } catch (IOException e) {
            log.error(e.getMessage());
        }
    }


    private void send(String data) throws IOException {
        if (session.isOpen()) {
            session.getBasicRemote().sendText(data);
        }
    }


    @OnClose
    public void close() {
        map.remove(account);
        log.info("{}断开了服务器连接", account);
    }

    @OnError
    public void error(Throwable error) {
        log.error("{}出现了异常", account);
        log.error(error.getMessage());
        map.remove(account);
    }

    @OnMessage
    public void getMessage(String message) throws IOException {
        try {
            SiteApplication value = local.get().readValue(message, SiteApplication.class);
            value.setReviewer(account);
            spaceService.updateSiteApplication(value);
            UserSocketServer.response(value);
            send(SocketResponseEntry.ADMIN_REQUEST_SUCCESS);
        } catch (SysException e) {
            send(SocketResponseEntry.ADMIN_REQUEST_FAIL);
        }
    }




}
